import os
import threading


class FileMonitor:


	def __init__(self):
		self.trackList = []
		self.fileHistory = {} #filename -> mtime

		self.newFileListeners = []
		self.removedFileListeners = []
		self.updatedFileListeners = []


	def registerNewFileListener(self, callback):
		self.newFileListeners.append(callback)
	

	def registerRemovedFileListener(self, callback):
		self.removedFileListeners.append(callback)
	

	def registerUpdatedFileListener(self, callback):
		self.updatedFileListeners.append(callback)


	def start(self):
		self.timer = threading.Timer(1.0, self._timerEvent)
		self.timer.start()
	
	
	def cancel(self):
		self.timer.cancel()


	def scan(self):
		self._checkNewFiles()
		self._checkRemovedFiles()
		self._checkUpdatedFiles()


	def track(self, path):
		if( not os.path.exists(path)):
			raise os.error

		self.trackList.append(path)
		
	
	def _timerEvent(self):
		self.scan()
		self.timer = threading.Timer(1.0, self._timerEvent)
		self.timer.start()
		


	def _checkNewFiles(self):
		for path in self.trackList:
			for root, dirs, files in os.walk(path):
				for name in files:
					filename = os.path.join(root, name)
					if(filename not in self.fileHistory):
						self._emitNewFile(filename)
						self.fileHistory[filename] = os.path.getmtime(filename)


	def _checkRemovedFiles(self):
		for filename in self.fileHistory.copy():
			if( not os.path.exists(filename)):
				self._emitRemovedFile(filename)
				del self.fileHistory[filename]


	def _checkUpdatedFiles(self):
		for filename in self.fileHistory:
			if( self.fileHistory[filename] != os.path.getmtime(filename)):
				self._emitUpdatedFile(filename)
				self.fileHistory[filename] = os.path.getmtime(filename)


	def _emitNewFile(self, path):
		for listener in self.newFileListeners:
			listener(path)


	def _emitRemovedFile(self, path):
		for listener in self.removedFileListeners:
			listener(path)


	def _emitUpdatedFile(self, path):
		for listener in self.updatedFileListeners:
			listener(path)
